package com.browsesoft.htmlcomponent;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.aote.component.replacer.Replacer;
import com.aote.component.replacer.ReplacerFactory;
import com.browsesoft.Entity;
import com.browsesoft.ExtendElement;
import com.browsesoft.Tools;

public class ReplacableParameterComponent extends HTMLBasicComponent {
	private HttpServletRequest request;

	// 多次替换的参数的初始状态
	Map substutite = new HashMap();

	public ReplacableParameterComponent(HTMLBasicComponent parent)
			throws Exception {
		super(parent);
	}

	public void init(HttpServletRequest request, Element e) throws Exception {
		super.init(request, element);
		this.getParamInitState(element, "onclick");
	}

	public void service(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		super.service(request, response);
		this.request = request;
	}

	protected void updateElement() throws Exception {
		super.updateElement();
		Element e = this.getElement();
		this.replaceParameter(request, e);
		this.disposSubstutite("onclick");
	}

	/**
	 * 替换onclick参数
	 */
	private void replaceParameter(HttpServletRequest request, Element e) {
		// 如果有不替换标记,则越过该元素
		if (e.hasAttribute("notreplace")) {
			return;
		}
		// 替换自己属性中所有的参数
		this.setParameter(e, request, "#");
		// 取所有子元素
		NodeList nl = e.getChildNodes();
		// 逐个替换除组件元素外，所有子元素的参数
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element) {
				Element element = (Element) node;
				if (element.hasAttribute("component")) {
					continue;
				}
				this.replaceParameter(request, element);
			}
		}
	}

	/**
	 * 替换元素中所有属性中的参数
	 * 
	 * @param e
	 * @param request
	 * @param tag
	 *            要替换参数的标记“＃”或“×”等
	 */
	private void setParameter(Element e, HttpServletRequest request, String tag) {
		// 元素所有属性
		NamedNodeMap map = e.getAttributes();
		// 逐个替换并设置属性
		for (int i = 0; i < map.getLength(); i++) {
			Node node = map.item(i);
			String value = node.getNodeValue();
			value = this.rplaceParameter(request, value, e, tag);
			String key = node.getNodeName();
			e.setAttribute(key, value);
		}
	}

	/**
	 * 根据参数替换器进行替换
	 */
	public String rplaceParameter(HttpServletRequest request,
			String attrValue, Element element, String tag) {
		StringBuffer sb = new StringBuffer(attrValue);
		int start = sb.indexOf(tag);
		while (start != -1) {
			int end = sb.indexOf(tag, start + 1);
			if (end == -1) {
				break;
			}
			String name = sb.substring(start + 1, end);
			String value = this.getValueByReplacerName(request, name, element);
			// 没有值，不替换
			if (value == null || value.equals("")) {
				start = sb.indexOf(tag, end + 1);
			} else {
				sb.replace(start, end + 1, value);
				int size = value.length() - name.length();
				start = sb.indexOf(tag, end + size);
			}
		}
		return sb.toString();
	}

	/**
	 * 通过replacerName得到要替换的参数值
	 */
	private String getValueByReplacerName(HttpServletRequest request,
			String paramName, Element element) {
		try {
			// 用替换器替换
			Replacer replacer = ReplacerFactory.getInstance().getReplacer(
					paramName);
			if (replacer != null) {
				String result = replacer.getParameter(request, this, element);
				return result;
			}
			// 如果是form组件，从实体中取参数替换
			if (this instanceof HTMLFormComponent) {
				HTMLFormModel model = (HTMLFormModel) this.getModel();
				String result = (String) model.getAttributes().get(paramName);
				if (result != null && !result.equals("")) {
					return result;
				}
			}
			if (this.getValue(paramName, this) != null) {
				String result = this.getValue(paramName, this);
				return result;
			}
			String result = request.getParameter(paramName);
			return result;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 通过组件换参数
	 */
	private String getValue(String paramName, HTMLBasicComponent component) {
		// 通过父组件的属性替换
		HTMLBasicComponent parent = component.getParent();
		if (parent != null && (parent instanceof HTMLFormComponent)) {
			Entity entity = (Entity) parent.getModel();
			// 父实体中有此属性
			if (entity.getAttributes().containsKey(paramName)) {
				String result = (String) entity.getAttributes().get(paramName);
				return result;
			}
		}
		// 如果父组件不是htmlformcomponent，就看父的父组件中有没有
		if (parent != null) {
			String str = this.getValue(paramName, parent);
			return str;
		}
		return null;
	}

	/**
	 * 替换自己的参数
	 */
	protected void replaceSelfParameter(HttpServletRequest request,
			HTMLBasicComponent component) {
		Element element = component.getElement();
		this.setParameter(element, request, "*");
	}

	/**
	 * 取要多次替换参数的属性的初始状态
	 */
	private void getParamInitState(Element element, String attributeName) {
		List list = ExtendElement.findElements(element, "moresub", "moresub");
		if (list.isEmpty()) {
			return;
		}
		Iterator iter = list.iterator();
		while (iter.hasNext()) {
			Element elem = (Element) iter.next();
			// 如果元素没有要替换参数的属性
			if (!elem.hasAttribute(attributeName)) {
				continue;
			}
			String value = elem.getAttribute(attributeName);
			// 如果是input等有name属性的元素
			String name = elem.getAttribute("name");
			if (name != null && !name.equals("")) {
				this.substutite.put(name, value);
				continue;
			}
			// 如果是textarea等有文本的元素
			String tagName = elem.getTagName();
			if (tagName.equals("textarea") || tagName.equals("a")) {
				String text = elem.getTextContent();
				this.substutite.put(text, value);
			}
		}
	}

	/**
	 * 进行多次参数替换
	 */
	private void disposSubstutite(String attributeName) {
		if (this.substutite.isEmpty()) {
			return;
		}
		Element element = this.getElement();
		Iterator iter = ExtendElement.findElements(element, "moresub",
				"moresub").iterator();
		while (iter.hasNext()) {
			Element elem = (Element) iter.next();
			if (elem.hasAttribute(attributeName)) {
				String key = new String();
				if (elem.hasAttribute("name")) {
					key = elem.getAttribute("name");
				} else {
					if (!elem.getTagName().equals("textarea")
							&& !elem.getTagName().equals("a")) {
						continue;
					}
					key = element.getTextContent();

				}
				String initValue = (String) this.substutite.get(key);
				String realValue = this.rplaceParameter(request, initValue,
						elem, "*");
				elem.setAttribute(attributeName, realValue);
			}
		}
	}

}
